/// <reference path="script.js" />

(function ($) {
	if (!window.html5today) window.html5today = {};

	html5today.tests = {
		init:function() {
			/// <summary>
			/// Initializes the test suite when the page content has been loaded.
			/// </summary>
			
			// load after page is ready
			$(html5today.tests.load);
		},
		
		
		load:function() {
			/// <summary>
			/// Loads the test suite when the page is ready.
			/// </summary>
			
			// run
			html5today.tests.run();
		},
		
		
		run: function() {
			/// <summary>
			/// Runs all tests in <see cref="html5today.tests.all"/>.
			/// </summary>

			for(var key in html5today.tests.all) {
				var f = html5today.tests.all[key]() || [];
				for(var i=0; i<f.length; i++){ html5today.tests.fail(key, f[i]); }
			}
			if(html5today.tests.$output){ $(document).scrollTop(html5today.tests.$output.position().top); }
		},
		
		
		fail: function(t,m,$o,f1,$t) {
			/// <summary>
			/// Writes the specified message (<paramref name="m"/>) to the test output area for the specified test 
			/// (<paramref name="t"/>).
			/// </summary>
			/// <param name="t">Name of the test that failed.</param>
			/// <param name="m">Error message.</param>
			/// <param name="$o">Placeholder for the test output element.</param>
			/// <param name="f1">Placeholder to indicate whether this is the first failure.</param>

			// use the cached output or create/cache it for the first time
			$o = html5today.tests.$output || (function(){
				f1 = true;
				return html5today.tests.$output = $('#container>footer')
					.append('<div id="testlog" style="background-color:#fcc;border:solid 1px #900"><h1>HTML5 Today Failed Tests</h1><ul></ul></div>')
					.find('#testlog>ul');
			})();
			
			// add test
			$t = $o.find('>li.'+t+'>ul');
			if(!(0 in $t)){
				$t = $o.append('<li class="' + t + '"><b>' + t + '</b><ul></ul></li>').find('>li.'+t+'>ul');
			}
			
			// add message
			if((m || '').length != 0) {
				$t.append('<li>'+m+'</li>');
			}
		},

		
		all: {
			html5_is_header_page_has_correct_counts: function () {
				// get expected numbers
				var f = [],                                            // failures
					$o = $('#appendixa>ul>li'), o = $o.length,         // organizations
					g = $o.find('>ul>li:not([asof],[level])').length,  // working groups
					$p = $o.find('li[level]'), p = $p.length,          // publications
					s = $p.filter(':not([level^=-])').length,          // specifications (not notes)
					pubCount = function(a){ for(var c=0,i=0; i<$p.length; i++) { var n = parseInt($($p[i]).attr(a)); if(n>0) c += n; } return c; },
					pg = pubCount('pages'),                            // pages
					b = pubCount('bugs'),                              // bugs
				
					// inline references
					$h5 = $('#html5>header'),
					$h5Spec = (function(){ for(var i=0; i<$p.length; i++) if($p[i].innerText.replace(' ', '') == 'HTML5') return $($p[i]); return null; })();
				
				// check number placeholders
				function test($x,x) {
					if(parseInt($x.text().replace(/,/g, '')) != x) {
						f.push('Count for "' + $x.attr('class') + '" should be ' + x);
						$x.text($x.text()+">>"+x)
							.css({ color:'#f00', fontWeight:'bold' })
							.parent().css({ border:'solid 1px #f00' });
					}
				}
				
				// exec number checks
				$h5.find('.orgs').each(function() { test($(this), o); });
				$h5.find('.groups').each(function() { test($(this), g); });
				$h5.find('.pubs').each(function() { test($(this), p); });
				$h5.find('.specs').each(function() { test($(this), s); });
				$h5.find('.pages').each(function() { test($(this), pg); });
				$h5.find('.bugs').each(function() { test($(this), b); });
				$h5.find('.html5pages').each(function() { test($(this), parseInt($h5Spec.attr('pages'))); });
				$h5.find('.html5bugs').each(function() { test($(this), parseInt($h5Spec.attr('bugs'))); });
				
				// if failed, show asides to make sure the effected areas are displayed
				if(0 in f){ $('html').addClass('no-js').find('aside').show(); }

				return f;
			},
			
			list_of_pubs_is_correct: function() {
				// get expected list items
				var f = [], 
					$ex = $('#appendixa>ul ul[class]'),      // parent of all the expected values
					$ac = $('#html5>section>ul ul[class]');  // parent of all the actual values
				
				// compare lists
				function test($ep,$ap,c,$e,$a,err,i,e,a,t,l) {
					/// <param name="$ep">Parent of the list of expected values.</param>
					/// <param name="$ap">Parent of the list of actual values.</param>
					/// <param name="c">CSS class name for the list to compare.</param>
					/// <param name="$e">Placeholder for the expected values.</param>
					/// <param name="$a">Placeholder for the actual values.</param>
					/// <param name="err">Placeholder for the function that handles errors.</param>
					/// <param name="i">Placeholder for the loop iterator.</param>
					/// <param name="e">Placeholder for the expected value within the loop.</param>
					/// <param name="a">Placeholder for the actual value within the loop.</param>
					/// <param name="t">Placeholder for the actual text, so the progress fallback text can be trimmed.</param>
					/// <param name="l">Placeholder for the actual level to be cached.</param>
					
					$e = $ep.filter('.'+c).children('li[level]');
					$a = $ap.filter('.'+c).children('li');
					if(!c){ return; }
					err = function(){ $(a||$a.parent()).css({ border:'solid 1px red' }).filter('li').css({ border:'solid 1px red', color:'#f00', fontWeight:'bold' }); };
					for(i=0; i<$e.length; i++) {
						e = $e[i];
						a = $a.length < i ? null : $a[i];
						l = $(a).children('progress').attr('value');
						t = a.innerText.replace(/^((Draft )?Note|Not Published|Working Draft|Last Call|(Candidate |Proposed )?Rec(ommendation)?)/,'');
						if(!a){ err(); f.push('The "'+c+'" list does not have the correct number of items'); break; }
						if(e.innerText != t) { err(); f.push('The "'+$a.parents('section:first').attr('id')+'/'+c+'" list has "'+t+'" and expected "'+e.innerText+'"'); continue; }
						if(e.level != l){ err(); f.push('The "'+$a.parents('section:first').attr('id')+'/'+c+'" list has "'+t+'" which is level "'+l+'" and should be "'+e.level+'"'); continue; }
					}
				}
				
				// exec item checks
				test($ex, $ac, 'css');
				test($ex, $ac, 'device');
				test($ex, $ac, 'ecma');
				test($ex, $ac, 'geo');
				test($ex, $ac, 'html');
				test($ex, $ac, 'ietf');
				test($ex, $ac, 'svg');
				test($ex, $ac, 'webapps');
				test($ex, $ac, 'webnot');
				test($ex, $ac, 'webrtc');

				// if failed, show asides to make sure the effected areas are displayed
				if(0 in f){ $('html').addClass('no-js').find('aside').show(); }

				return f;
			}
		}
	};
})(jQuery);


// initialize now
html5today.tests.init();
